package com.sinodata.bsm.center.web.action.resource;

import java.util.*;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.springframework.beans.factory.annotation.Autowired;

import com.sinodata.bsm.center.cache.*;
import com.sinodata.bsm.center.purview.FunctionConstants;
import com.sinodata.bsm.center.purview.UserFunctionValidate;
import com.sinodata.bsm.center.service.relation.ResRelationService;
import com.sinodata.bsm.center.service.resource.ResGroupService;
import com.sinodata.bsm.center.service.resource.ResService;
import com.sinodata.bsm.center.user.UserUtil;
import com.sinodata.bsm.center.util.web.Struts2Utils;
import com.sinodata.bsm.center.web.action.BaseAction;
import com.sinodata.bsm.common.exception.AppException;
import com.sinodata.bsm.common.vo.*;
import com.sinodata.bsm.common.constants.*;

public class ResGroupAction extends BaseAction<ResGroup> {
    private ResGroup entity;
    private Long id;
    private Long[] ids;
    @Autowired
    private ResGroupService resGroupService;
    @Autowired
    private ResGroupCache resGroupCache;
    @Autowired
    private MotiResRelCache motiResRelCache;
    @Autowired
    private ResService resService;
    @Autowired
    private MonitorTypeCache monitorTypeCache;
    @Autowired
    private ResRelationCache resRelationCache;
    @Autowired
    private ResRelationService resRelationService;
    @Autowired
    private ResTypeCache resTypeCache;
    @Autowired
    private ResViewCache resViewCache;

    @Override
    public String delete() throws Exception {
        List<MotiResRel> relList = motiResRelCache.findByResGroupId(this.id);
        if (relList != null && relList.size() > 0) {
            throw new AppException("资源组已关联资源，不能删除。");
        } else {
            resGroupService.deleteResGroup(resGroupService.get(id));
        }
        Map<String, List<String>> map = (Map<String, List<String>>) request.getSession().getAttribute("nodeTrace");
        Long lastViewId = (Long) request.getSession().getAttribute("lastView");
        List<String> traceList = map.get(String.valueOf(lastViewId.longValue()));
        for (int i = traceList.size() - 1; i >= 0; i--) {
            String[] ids = traceList.get(i).split("[|]");
            if (ids[0].equals("5") && ids[1].equals(String.valueOf(this.id.longValue()))) {
                traceList.remove(i);
                break;
            }
        }
        if (traceList.size() == 0) {
            map.remove(String.valueOf(lastViewId.longValue()));
        }
        renderText("true");
        return null;
    }

    @Override
    public String input() throws Exception {
        String ntype = request.getParameter("ntype");
        String pId = request.getParameter("pId");
        MonitorType monitorType = null;
        Res res = null;
        boolean isRoot = false;
        if (pId != null && !pId.equals("")) {
            this.id = Long.parseLong(pId);
            if (ntype.equals("4")) {
                monitorType = monitorTypeCache.get(id);
            } else if (ntype.equals("2")) {
                //说明是资源
                res = resService.get(id);
            } else {
                entity = resGroupService.get(id);
            }
        } else {
            isRoot = true;
        }

        request.setAttribute("isRoot", isRoot);
        String viewId = request.getParameter("viewId");
        ResView resView = resViewCache.get(Long.parseLong(viewId));
        request.setAttribute("resView", resView);
        request.setAttribute("ntype", ntype);
        request.setAttribute("monitorType", monitorType);
        request.setAttribute("resGroup", entity);
        request.setAttribute("res", res);

        return "input";
    }

    public String initUpdate() throws Exception {
        entity = resGroupService.get(id);
        String pname = null;
        if (entity.getParentId() != null) {
            pname = resGroupService.get(entity.getParentId().longValue()).getName();
        } else {
            if (entity.getType() == 2) {
                Res res = resService.get(entity.getResId());
                pname = res.getName();
            } else if (entity.getType() == 4) {
                MonitorType monitorType = monitorTypeCache.get(entity.getMonitorTypeId());
                pname = monitorType.getName();
            } else if (entity.getType() == 1) {
                ResView resView = resViewCache.get(entity.getResViewId());
                pname = resView.getName();
            }
        }
        request.setAttribute("pname", pname);
        request.setAttribute("resGroup", entity);
        return "update";
    }

    public String update() throws Exception {
        entity = resGroupService.get(id);
        String name = request.getParameter("name");
        String descript = request.getParameter("descript");
        if (name != null && !name.equals("")) {
            entity.setName(name);
        }
        entity.setDescript(descript);
        resGroupService.saveOrUpdateResGroup(entity);
        return null;
    }

    private boolean isChildRes(long resId, Map<Long, Boolean> validCache, Set<Long> relationTypesIds) {
        Boolean isSysAdmin = (Boolean) request.getSession().getAttribute("UserIsGuest");
        if (isSysAdmin == null) {
            if (UserUtil.getInstance().isSysAdmin(UserUtil.getInstance().getCurrentUserId()) || UserUtil.getInstance().isGuest(UserUtil.getInstance().getCurrentUserId())) {
                request.getSession().setAttribute("UserIsGuest", true);
                return true;
            } else {
                request.getSession().setAttribute("UserIsGuest", false);
            }
        } else {
            if (isSysAdmin.TRUE) {
                return true;
            }
        }
        if (validCache.containsKey(resId)) {
            return validCache.get(resId);
        }
        List<ResRelation> relations = resRelationCache.getResRelationsOfRes(resId);
        if (relations != null) {
            for (ResRelation resRelation : relations) {
                if (resRelation.getEndId().longValue() == resId && relationTypesIds.contains(resRelation.getRelationTypeId().longValue())) {
                    long pResId = resRelation.getStartId();
                    if (validCache.containsKey(pResId)) {
                        if (validCache.get(pResId)) {
                            return true;
                        }
                    } else {
                        boolean bln = isChildRes(pResId, validCache, relationTypesIds);
                        validCache.put(pResId, bln);
                        if (bln) {
                            return true;
                        }
                    }
                }
            }
        }
        validCache.put(resId, false);
        return false;
    }

    private Map<Long, Boolean> getUserPrivilegeMap() {
        Map<Long, Boolean> map = (Map<Long, Boolean>) request.getSession().getAttribute("UserPrivilegeMap");
        if (map == null) {
            map = new HashMap<Long, Boolean>(2000);
            List<Long> resList = UserFunctionValidate.getResIdListForUser(FunctionConstants.VIEW_RES);
            for (Long resId : resList) {
                map.put(resId, true);
            }
        }
        return map;

    }

    private Integer[] genResGroup(ResGroup g, Map<Long, List<ResGroup>> childMap, Set<Long> relationTypesIds, Set<Long> includeList) {
        List<MotiResRel> relList = motiResRelCache.findByResGroupId(g.getId());
        int num = 0;
        int maxStatus = 1;
        if (childMap.containsKey(g.getId().longValue())) {
            List<ResGroup> children = childMap.get(g.getId().longValue());
            for (ResGroup child : children) {
                Integer[] childJson = genResGroup(child, childMap, relationTypesIds, includeList);
                num += childJson[1];
                if (maxStatus < childJson[0]) {
                    maxStatus = childJson[0];
                }
            }
        }
        if (relList != null) {
            for (MotiResRel rel : relList) {
                Res res = null;
                if ((res = resService.get(rel.getResId())) != null && isChildRes(res.getId(), getUserPrivilegeMap(), relationTypesIds)) {
                    if (maxStatus < res.getHealthStatus()) {
                        maxStatus = res.getHealthStatus();
                    }
                    num++;
                    includeList.add(res.getId().longValue());
                }
            }
        }

        Integer[] values = new Integer[] { maxStatus, num };

        return values;
    }

    private JSONObject genResGroupNode(ResGroup g, Map<Long, List<ResGroup>> childMap, Set<Long> relationTypesIds) {
        JSONObject json = new JSONObject();
        long pid = g.getParentId() == null ? 0 : g.getParentId();
        json.element("id", "5|" + g.getId() + "|" + pid);
        JSONArray arr = new JSONArray();
        if (childMap.containsKey(g.getId().longValue())) {
            List<ResGroup> children = childMap.get(g.getId().longValue());
            for (ResGroup child : children) {
                JSONObject childJson = genResGroupNode(child, childMap, relationTypesIds);
                arr.add(childJson);
            }
        }
        json.element("iconSkin", "type1");
        json.element("name", g.getName());
        json.element("children", arr);
        return json;
    }

    public String tree() throws Exception {
        String multiple = request.getParameter("m");
        if (multiple == null) {
            request.setAttribute("multiple", false);
        } else {
            request.setAttribute("multiple", true);
        }

        return "tree";
    }

    private JSONObject genMonitorTypeNode(MonitorType mt) {
        JSONObject json = new JSONObject();
        String nodeId = "4|" + mt.getId() + "|0";
        json.element("id", nodeId);
        json.element("name", mt.getName());
        json.element("open", true);
        json.element("iconSkin", "type1");
        return json;
    }

    public String genResGroupTree() throws Exception {
        String monitorTypeId = request.getParameter("monitorTypeId");

        Set<Long> relationTypeIds = findRelationTypeIds();
        JSONArray jsonArray = new JSONArray();
        if (monitorTypeId != null) {
            //说明只展现这个类别下的资源组
            JSONObject mtjson = genMonitorTypeNode(monitorTypeCache.get(Long.parseLong(monitorTypeId)));
            Map<Long, List<ResGroup>> tmpMap = new HashMap<Long, List<ResGroup>>();
            List<ResGroup> rootResGroup = new ArrayList<ResGroup>();
            List<ResGroup> groups = resGroupCache.findByMoitTypeId(Long.parseLong(monitorTypeId));
            if (groups == null) {
                groups = new ArrayList<ResGroup>(0);
            }
            for (ResGroup g : groups) {
                if (g.getParentId() != null) {
                    List<ResGroup> arr = tmpMap.get(g.getParentId().longValue());
                    if (arr == null) {
                        arr = new ArrayList<ResGroup>();
                        tmpMap.put(g.getParentId().longValue(), arr);
                    }
                    arr.add(g);
                } else {
                    rootResGroup.add(g);
                }
            }
            JSONArray tmpArray = new JSONArray();
            for (ResGroup g : rootResGroup) {
                JSONObject json = genResGroupNode(g, tmpMap, relationTypeIds);
                tmpArray.add(json);
            }
            mtjson.element("children", tmpArray);
            jsonArray.add(mtjson);
        } else {
            //展现全部

        }

        renderText(jsonArray.toString());
        return null;
    }

    public String view() throws Exception {

        String ntype = request.getParameter("ntype");
        MonitorType monitorType = null;
        List<ResGroup> children = null;
        List<Res> unsortList = new ArrayList<Res>();

        if (ntype.equals("4")) {
            monitorType = monitorTypeCache.get(id);
            List<ResGroup> allResGroup = resGroupCache.findByMoitTypeId(id);
            if (allResGroup == null) {
                allResGroup = new ArrayList(0);
            }
            children = new ArrayList<ResGroup>();
            for (ResGroup g : allResGroup) {
                if (g.getParentId() == null)
                    children.add(g);
            }
        } else {
            entity = resGroupService.get(id);
            children = resGroupCache.findByParent(id);
            // if(children.size()>0){
            List<MotiResRel> list = motiResRelCache.findByResGroupId(id);
            if (list != null && list.size() > 0) {
                for (MotiResRel rel : list) {
                    unsortList.add(resService.get(rel.getResId()));
                }
            }
            //  }
        }
        Map<Long, List<ResGroup>> childMap = resGroupCache.findAllChildren();
        Set<Long> relationTypeIds = findRelationTypeIds();
        List<Object[]> childInfo = new ArrayList<Object[]>();

        Set<Long> includeList = new HashSet<Long>();
        Collections.sort(children);
        for (ResGroup root : children) {
            Integer[] values = genResGroup(root, childMap, relationTypeIds, includeList);
            childInfo.add(new Object[] { root, values });
        }
        if (ntype.equals("4")) {
            Collection<Res> ress = resService.findAll();
            for (Res res : ress) {
                Long mt = resTypeCache.getMoitTypeId(res.getResTypeId());
                if (mt == null || mt.longValue() != this.id || includeList.contains(res.getId().longValue())) {
                    continue;
                }
                if (isChildRes(res.getId(), getUserPrivilegeMap(), relationTypeIds)) {
                    //未分类的
                    unsortList.add(res);
                }
            }
        }
        JSONArray array = new JSONArray();
        for (Res res : unsortList) {
            if (res == null) {
                continue;
            }
            JSONObject object = new JSONObject();
            object.element("checkbox", "<input type='checkbox' name='dt_check' id='dt_check' value='" + res.getId() + "'>");
            object.element("id", res.getId());
            object.element("name", res.getName());
            object.element("resTypeName", resTypeCache.get(res.getResTypeId()).getName());
            object.element("ip", res.getIp());
            object.element("healthStatus", "<span class='health' id=child" + res.getId() + " value=" + res.getHealthDegree() + "></span>");
            array.add(object);

        }
        request.setAttribute("ntype", ntype);
        request.setAttribute("monitorType", monitorType);
        request.setAttribute("resGroup", entity);
        request.setAttribute("children", childInfo);
        request.setAttribute("resList", array);
        String viewId = request.getParameter("viewId");
        request.setAttribute("viewId", viewId);
        return "view";
    }

    private Set<Long> findRelationTypeIds() {
        Set<RelationType> relationTypes = resRelationService.getSelfAndSubRelationType();
        Set<Long> relationTypesIds = new HashSet<Long>();
        for (RelationType type : relationTypes) {
            relationTypesIds.add(type.getId().longValue());
        }
        return relationTypesIds;
    }

    @Override
    public String list() throws Exception {

        return null;
    }

    @Override
    protected void prepareModel() throws Exception {
        if (id == null) {
            entity = new ResGroup();
        } else {
            entity = resGroupService.get(id);
        }
    }

    @Override
    public String save() throws Exception {

        Long parentId = entity.getParentId();
        String isRoot = request.getParameter("isRoot");
        if (parentId != null) {
            ResGroup pGroup = resGroupService.get(parentId);
            entity.setMonitorTypeId(pGroup.getMonitorTypeId());
            entity.setResId(pGroup.getResId());
            entity.setResViewId(pGroup.getResViewId());
            entity.setType(pGroup.getType());
        }
        if (isRoot != null) {
            //则是顶级资源组，并且靠在resView下
            entity.setParentId(null);
            entity.setResId(null);
            entity.setMonitorTypeId(null);
            String resViewId = request.getParameter("resViewId");
            entity.setResViewId(Long.parseLong(resViewId));
            entity.setType(1);
        }
        resGroupService.saveOrUpdateResGroup(entity);
        renderText("true");
        return null;
    }

    public String moveMotiResRel() throws Exception {

        entity = resGroupService.get(id);
        for (Long resId : this.ids) {
            resGroupService.deleteMotiResRel(this.id, resId);
            resRelationService.removeResRelationByResId(entity.getResId(), resId);
        }
        if (entity.getResId() != null)
            resRelationService.refreshResHealthStatus(entity.getResId());
        renderText("true");

        return null;
    }

    public String saveMotiResRel() throws Exception {
        String ntype = request.getParameter("ntype");
        try {
            Set<Long> inValidIds = new HashSet<Long>();
            StringBuffer error = new StringBuffer();
            if (ntype.equals("5")) {
                //id代表的是resGroup
                ResGroup group = resGroupService.get(this.id);
                if (group.getType() == 4) {
                    //则代表resId有限制，只能在关联在的monitorType下
                    for (Long resId : this.ids) {
                        Res res = resService.get(resId);
                        Long mtId = resTypeCache.getMoitTypeId(res.getResTypeId());
                        if (mtId == null || (mtId.longValue() != group.getMonitorTypeId())) {
                            error.append("<br>" + res.getName() + " 不属于  " + monitorTypeCache.get(group.getMonitorTypeId()).getName());
                            inValidIds.add(resId);
                            continue;
                        }
                        //先删除基础架构视图下的其它资源组关系
                        List<ResGroup> groups = resGroupCache.findByMoitTypeId(group.getMonitorTypeId());
                        if (groups != null) {
                            for (ResGroup g : groups) {
                                motiResRelCache.remove(g.getId(), res.getId());
                                resGroupService.deleteMotiResRel(g.getId(), resId);
                            }
                        }
                    }

                } else if (group.getType() == 2) {
                    //则是资源
                    List<Long> parents = resService.findParentIdsByResId(group.getResId()); // 当前资源的所有父资源
                    parents.add(group.getResId());
                    Long[] resTypes = ResGroupTypeMap.getResType(group.getContainType());
                    for (Long child : this.ids) {
                        Res res = resService.get(child);
                        if (resTypes != null && resTypes.length > 0) {
                            //则代表有约束
                            Set<Long> pSet = new HashSet<Long>();
                            ResType resType = null;
                            Long resTypeId = res.getResTypeId();
                            do {
                                resType = resTypeCache.get(resTypeId);
                                pSet.add(resType.getId());
                            } while ((resTypeId = resType.getParentId()) != null);
                            boolean isFounded = false;
                            for (Long tmp : resTypes) {
                                if (pSet.contains(tmp)) {
                                    isFounded = true;
                                    break;
                                }
                            }
                            if (!isFounded) {
                                error.append("<br>资源【" + res.getName() + "】不能挂在该资源组");
                                inValidIds.add(child);
                                continue;
                            }
                        }

                        if (parents.contains(child.longValue())) {
                            error.append("<br>资源【" + res.getName() + "】与父资源建立关联关系错误");
                            inValidIds.add(child);
                            continue;
                        }
                        ResRelation relation = new ResRelation();
                        relation.setEndId(child);
                        relation.setStartId(group.getResId());
                        relation.setRelationTypeId(RelationConstants.SUPPORT);
                        resRelationService.addResRelation(relation);
                    }
                    resRelationService.refreshResHealthStatus(group.getResId());
                } else if (group.getType() == 1) {
                    //是与资源视图挂靠
                }
            } else {

                //id 代表的是 monitorType, 代表当前的resId移除关系。 并且resId要满足 符合移动在所属的monitorType下
                for (Long resId : this.ids) {
                    inValidIds.add(resId);
                    Res res = resService.get(resId);
                    Long mtId = resTypeCache.getMoitTypeId(res.getResTypeId());
                    if (mtId == null || mtId.longValue() != this.id) {
                        error.append("<br>资源【" + res.getName() + "】不属于  " + monitorTypeCache.get(this.id).getName());
                    } else {
                        List<ResGroup> groups = resGroupCache.findByMoitTypeId(mtId);
                        if (groups != null) {
                            for (ResGroup g : groups) {
                                resGroupService.deleteMotiResRel(g.getId(), res.getId());
                            }
                        }
                    }
                }
            }
            String msg = null;
            if (!error.toString().equals("")) {
                msg = error.toString().substring(4);
            }
            if (msg != null) {
                renderText(msg);
                return null;
            }
            if (ntype.equals("5")) {
                for (Long resId : this.ids) {
                    if (inValidIds.contains(resId.longValue())) {
                        continue;
                    }
                    MotiResRel _motiResRel = new MotiResRel();
                    _motiResRel.setResGroupId(id);
                    _motiResRel.setResId(resId);
                    try {
                        resGroupService.saveMotiResRel(_motiResRel);
                    } catch (AppException ex) {
                        logger.error("", ex);
                    }
                }
            }
            renderText("true");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    @Override
    public ResGroup getModel() {

        return entity;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long[] getIds() {
        return ids;
    }

    public void setIds(Long[] ids) {
        this.ids = ids;
    }

}
